import java.util.ArrayList;
import java.util.List;

/* This Class stores: 
 *  - a queue of nodes waiting to be crawled.
 *  - a queue of CrawlResults waiting to be writing to disk.
 *  
 *  This Class will:
 *  - Spawn CrawlThreads
 *    - CrawlThreads will take elements from the nodeQueue and crawl them. (pull)
 *    - It will then enqueue its result to the CrawlMaster's writeQueue.
 *  - Periodically check the writeQueue, if it is not empty, 
 *    it will remove an element, and write it to disk.
 */


public class CrawlMaster extends Thread{
	
    int timeout = 30; // Default is 30 seconds
    int numThreads = 30;
    
    ObjectWriter crawlWriter;
    
    Queue allHosts = new Queue();
    Queue nodeQueue = new Queue(); // A queue of nodes waiting to be crawled.
    Queue writeQueue = new Queue(); // A queue of CrawlResults waiting to be writing to disk.
    List<CrawlThread> threads = new ArrayList<CrawlThread>(); // Store the list of threads so we can kill them later.
    
    // Constructor
	public CrawlMaster(String addr, int port, int t, String path) {
		timeout = t;
		crawlWriter = new ObjectWriter(path);
		nodeQueue.enqueue(addr+":"+port); //Add bootstrap node to our list of nodes that are waiting to be crawled.
	}
			
	public void run () {		
		
		System.out.println("Starting " + numThreads + " Threads...");
        // Creates Threads that Crawls
        for(int i=0; i<numThreads; i++) {
        	threads.add( new CrawlThread(nodeQueue, writeQueue, allHosts, timeout, i) );
        }
        // Start the threads we just created
        for(int i=0; i<numThreads; i++) {
        	threads.get(i).start();
        }
        
        // Main Loop
        CrawlResult crawlResult;
        while(true) {
        	        	
        	//System.out.println("NODE QUEUE SIZE: " + nodeQueue.size());
        	// Check writeQueue
        	try {
                crawlResult = (CrawlResult)writeQueue.dequeue();
                crawlWriter.write(crawlResult);
                
            } catch (InterruptedException e) {
//            	System.out.println("Master Interupted");
            	// Kill all of our children threads
                for(int i=0; i<numThreads; i++) {
                	threads.get(i).interrupt();
                }
                // Properly close our ObjectOutputStream
                crawlWriter.close();
                return;
            } 
            
            
        }
        
		
	}
	
	
}
